package com.echo.im.client.handler.suport;


import com.alibaba.fastjson2.JSONObject;
import com.echo.im.client.handler.MessageHandler;
import com.echo.im.client.status.OnlineStatusService;
import com.echo.im.common.enums.IMCmdType;
import com.echo.im.common.enums.IMTerminalType;
import com.echo.im.common.enums.MessageType;
import com.echo.im.common.model.info.IMRecvInfo;
import com.echo.im.common.model.info.IMSendInfo;
import com.echo.im.common.model.info.IMUserInfo;
import com.echo.im.common.model.message.IMPrivateMessage;
import com.echo.im.common.model.mq.OfflineMsgMqInfo;
import com.echo.im.common.vo.message.PrivateMessageVO;
import com.echo.im.infrastructure.mq.event.model.push.PushMessageEvent;
import com.echo.im.infrastructure.mq.event.model.store.OfflineStoreEvent;
import com.echo.im.infrastructure.mq.event.producer.EventPublisher;
import com.echo.im.infrastructure.session.SessionContext;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;


import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: echo
 * @time: 2024-08-14
 */
@Component
@RequiredArgsConstructor
public class PrivateMessageHandler implements MessageHandler<IMPrivateMessage> {

    private final PushMessageEvent pushMessageEvent;
    private final OfflineStoreEvent offlineStoreEvent;
    private final EventPublisher eventPublisher;
    private final OnlineStatusService onlineStatusService;

    @Override
    public void handleMessage(IMPrivateMessage message) {

        //得到serverId terminalList
        Map<Integer, List<Integer>> serverIdTerminalListMap = onlineStatusService.getServerIdTerminalListMap(message.getRecvId(), message.getRecvTerminals());

        //如果不为空则发送消息
        if(!serverIdTerminalListMap.isEmpty()) {
            for (Map.Entry<Integer, List<Integer>> entry : serverIdTerminalListMap.entrySet()){
                List<Integer> terminalList= entry.getValue();
                Integer serverId = entry.getKey();

                // 组装消息
                IMRecvInfo<PrivateMessageVO> recvInfo = new IMRecvInfo<>();
                recvInfo.setCmd(IMCmdType.PRIVATE_MESSAGE.code());
                recvInfo.setSender(message.getSender());

                List<IMUserInfo> userInfos = new ArrayList<>();
                for (Integer terminal : terminalList) {
                    userInfos.add(new IMUserInfo(message.getRecvId(), terminal));
                }
                recvInfo.setReceivers(userInfos);
                recvInfo.setData(message.getData());
                recvInfo.setNeedOfflineStore(message.getIsNeedOfflineStore());

                // 如果对方在线，将数据推送到消息队列，等待拉取推送
                eventPublisher.publishWithServerId(pushMessageEvent, recvInfo,serverId.toString());
            }
        }else {
            if(message.getIsNeedOfflineStore()){

                //如果为空就证明用户不在线，那么就直接走离线逻辑
                OfflineMsgMqInfo offlineMsgMqInfo = new OfflineMsgMqInfo(message.getRecvId(), message.getData().getId(),OfflineMsgMqInfo.OfflineMsgEnum.PRIVATE_OFFLINE_MESSAGE);
                eventPublisher.publish(offlineStoreEvent,offlineMsgMqInfo);

                //并伪装 ACK
                if (message.getData().getSeq()!=null){
                    PrivateMessageVO privateMessageVO = new PrivateMessageVO();
                    privateMessageVO.setSendId(message.getRecvId());
                    privateMessageVO.setRecvId(message.getSender().getId());
                    privateMessageVO.setType(MessageType.ACK.code());
                    //构造ACK包
                    LinkedHashMap<String, Long> map = new LinkedHashMap<>();
                    map.put("seq",message.getData().getSeq());
                    map.put("messageId",message.getData().getId());
                    privateMessageVO.setContent(JSONObject.toJSONString(map));

                    IMSendInfo<Object> sendInfo = new IMSendInfo<>();
                    sendInfo.setCmd(IMCmdType.PRIVATE_MESSAGE.code());
                    sendInfo.setData(privateMessageVO);
                    SessionContext.getChannel().writeAndFlush(sendInfo);
                }
            }
        }

        // 先判断此消息是否需要推给自己，然后推送给自己的其他终端，在撤回消息的时候会用到
        if (message.getSendToSelf()) {
            // 获取所有接收端的 serverId但是除去当前端
            List<Integer> recvTerminals= IMTerminalType.codes().stream().filter(terminal -> !terminal.equals(message.getSender().getTerminal())).collect(Collectors.toList());

            serverIdTerminalListMap = onlineStatusService.getServerIdTerminalListMap(message.getSender().getId(),recvTerminals);

            serverIdTerminalListMap.forEach((serverId, terminalList) -> {
                // 获取终端连接的 serverId
                IMRecvInfo<PrivateMessageVO> recvInfo = new IMRecvInfo<>();
                recvInfo.setCmd(IMCmdType.PRIVATE_MESSAGE.code());
                recvInfo.setSender(message.getSender());
                List<IMUserInfo> userInfos = new ArrayList<>();
                for (Integer terminal : terminalList) {
                    userInfos.add(new IMUserInfo(message.getSender().getId(), terminal));
                }
                recvInfo.setReceivers(userInfos);

                recvInfo.setData(message.getData());
                recvInfo.setNeedOfflineStore(false);

                eventPublisher.publishWithServerId(pushMessageEvent,recvInfo,serverId.toString());
            });
        }

    }


}
